using System;
using System.Collections.Generic;
using System.Text;

using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;

using ZoneFiveSoftware.Common.Visuals;
using ZoneFiveSoftware.Common.Visuals.Fitness;


namespace PolarImport.DeviceImporter
{
    class PolarCS200 : IFitnessDevice 
    {
        /// <summary>
        /// Constructor of the FitnessDevice. Set GUID, image, name and connection information.
        /// </summary>
        public PolarCS200()
        {
            this.id = new Guid("FFB6946D-3EF6-48c6-ADFF-5D620EACEF34");
            this.image = Properties.Resources.Img_Polar_HRM_CS200;
            this.name = "Polar CS200";
            this.connection = "SonicLink";
        } 
        #region IFitnessDevice Member

        /// <summary>
        /// Something about Properties of the connection... 
        /// </summary>
        /// <param name="configurationInfo">???</param>
        /// <returns>Properties?</returns>
        public string Configure(string configurationInfo)
        {
            return "";
        }

        /// <summary>
        /// The name and the connection method of this POLAR HRM.
        /// </summary>
        /// <param name="configurationInfo">???</param>
        /// <returns>The name and the connection method of this POLAR HRM.</returns>
        public string ConfiguredDescription(string configurationInfo)
        {
            return name + Environment.NewLine + connection;
        }

        #endregion

        #region IDataImporter Member

        /// <summary>
        /// The name of this POALR HRM.
        /// </summary>
        public string Name
        {
            get { return name; }
        }

        /// <summary>
        /// The unique ID of this FitnessDevice.
        /// </summary>
        public Guid Id
        {
            get { return id; }
        }

        /// <summary>
        /// The image to represent this POLAR HRM in import dialog of SportTracks.
        /// </summary>
        public System.Drawing.Image Image
        {
            get { return image; }
        }

        public bool Import(string configurationInfo, IJobMonitor monitor, IImportResults importResults)
        {
            int version = PolarHRM.GetLibraryVersion();
            PolarImportForm ImportWindow = new PolarImportForm();
            ImportWindow.Text = name;
            ImportWindow.Show();
            if (MessageDialog.Show(string.Format(Properties.Resources.PolarImport_General_PlaceHRMSonicLink, name),
                name, System.Windows.Forms.MessageBoxButtons.OKCancel, System.Windows.Forms.MessageBoxIcon.Information) ==
                System.Windows.Forms.DialogResult.Cancel)
            {
                return false;  // Abort by user
            }
            monitor.StatusText = Properties.Resources.PolarImport_General_ReadingData;
            monitor.PercentComplete = 0.0f;
            int readdata = PolarHRM.ReadSonicLinkData(ImportWindow.Handle, (int)MonitorType.HRM_CS200 , 0, 2, false);
            switch (readdata)
            {
                case 0: // Cancelled
                    {
                        monitor.StatusText = Properties.Resources.PolarImport_General_ReadingCancelled;
                        monitor.ErrorText = Properties.Resources.PolarImport_General_ReadingCancelled;
                        ImportWindow.Dispose();
                        return false;
                    }
                case 1: // Successfull
                    {
                        monitor.StatusText = Properties.Resources.PolarImport_General_ReadingSucces;
                        ImportWindow.Dispose();
                        return ProcessData(monitor, importResults);
                    }
                case 2: // Retry
                    {
                        monitor.StatusText = Properties.Resources.PolarImport_General_Retry;
                        // Call the import function recursive!
                        ImportWindow.Dispose();
                        return Import(configurationInfo, monitor, importResults);
                    }
            }
            monitor.ErrorText = Properties.Resources.PolarImport_General_Not_implemented;
            ImportWindow.Dispose();
            return false;
        }
        /// <summary>
        /// Processing of the raw data read by Import function. Store processed data in corresponding
        /// SportTracks structures
        /// </summary>
        /// <param name="monitor">The active job monitor for this import. Shows progress of import.</param>
        /// <param name="importResults">The imported data. This data is processed by SportTrack safter successful import.</param>
        /// <returns>True, if data processing was successful.<br></br>False, if data processing fails.</returns>
        private bool ProcessData(IJobMonitor monitor, IImportResults importResults)
        {
            int FitnessFileCount = PolarHRM.GetFitnessFileCount();
            if (FitnessFileCount > 0)
            {
                for (int FitnessFile = 0; FitnessFile < FitnessFileCount; FitnessFile++)
                {
                    monitor.StatusText = string.Format(Properties.Resources.PolarImport_Import_FitnessFileCount +
                        Environment.NewLine, FitnessFileCount) +
                        string.Format(Properties.Resources.PolarImport_Import_ProcessingFile, FitnessFile);
                    monitor.PercentComplete = (float)FitnessFile / (float)FitnessFileCount;

                    PolarHRM.AnalyzeFile(FitnessFile, 0);
                    // See, if the user records his hr as bpm or as %hrmax
                    float HRFactor = 1f;
                    if (PolarHRM.GetRecParam(RecData.REC_HR_LIMIT_VIEW) == 1)
                    {
                        HRFactor = (float)PolarHRM.GetRecParam(RecData.REC_USER_HR_MAX) / 100f;
                    }
                    DateTime startdate = PolarHRM.ConvertHRMDate(PolarHRM.GetRecParam(RecData.REC_START_DATE));
                    DateTime starttime = PolarHRM.ConvertHRMTime(PolarHRM.GetRecParam(RecData.REC_START_TIME));
                    DateTime startDateTime = new DateTime(startdate.Year, startdate.Month, startdate.Day, starttime.Hour, starttime.Minute, starttime.Second);
                    // Maybe it is not necessary to convert to UniversalTime. For me it works. The StartTime is correct. Without
                    // this the StartTime is 1 hour to much.
                    startDateTime = startDateTime.ToUniversalTime();
                    
                    IActivity activity = importResults.AddActivity(startDateTime);

                    activity.AverageHeartRatePerMinuteEntered = PolarHRM.GetRecParam(RecData.REC_AVE_HRATE) * HRFactor;
                    activity.MaximumHeartRatePerMinuteEntered = PolarHRM.GetRecParam(RecData.REC_MAX_HRATE) * HRFactor;
                    activity.TotalTimeEntered = new TimeSpan(0, 0, PolarHRM.GetRecParam(RecData.REC_REC_LENGTH) / 1000);
                    activity.TotalCalories = PolarHRM.GetRecParam(RecData.REC_CALORIES);
                    activity.AverageCadencePerMinuteEntered = PolarHRM.GetRecParam(RecData.REC_AVG_CAD);
                    activity.MaximumCadencePerMinuteEntered = PolarHRM.GetRecParam(RecData.REC_MAX_CAD);
                    activity.TotalDistanceMetersEntered = PolarHRM.GetRecParam(RecData.REC_TRIP_DIST_STOP) * 100;
                    activity.Weather.TemperatureCelsius = PolarHRM.GetRecParam(RecData.REC_AVE_TEMP) / 10.0f;
                    activity.Notes += Properties.Resources.PolarImport_Import_DirectImportFrom + " " + name + Environment.NewLine;
                    activity.UseEnteredData = true;
                    activity.HasStartTime = true;
                    // Process the laps
                    int totalLaps = PolarHRM.GetNbrOfIntTimes();
                    if (totalLaps > 1)
                    {
                        int oldDistance = 0;
                        int actDistance = 0;
                        TimeSpan oldLapDuration = new TimeSpan(0, 0, 0);
                        TimeSpan actLapDuration = new TimeSpan(0, 0, 0);
                        TimeSpan fiveSeconds = new TimeSpan(0, 0, 5);
                        DateTime LapStartTime = startDateTime;
                        DateTime LapEndTime = DateTime.MinValue;
                        DateTime ActTime = DateTime.MinValue;
                        activity.CadencePerMinuteTrack = new NumericTimeDataSeries();
                        activity.HeartRatePerMinuteTrack = new NumericTimeDataSeries();
                        for (int LapNumber = 0; LapNumber < totalLaps; LapNumber++)
                        {
                            

                            // Fill in data to distance track.
                            if (LapNumber == 0)
                            {
                                activity.DistanceMetersTrack = new DistanceDataTrack();
                                activity.DistanceMetersTrack.Add(startDateTime, 0f);
                            }

                            // Get Lap Duration and Lap Distance. (NOTE: This are cummulated values!)
                            actLapDuration = new TimeSpan(0, 0, PolarHRM.GetIntTimeData(LapNumber, LapData.INT_INT_TIME) / 10);
                            actDistance = PolarHRM.GetIntTimeData(LapNumber, LapData.INT_LAP_DISTANCE);
                            // add to distance track
                            activity.DistanceMetersTrack.Add(startDateTime + actLapDuration, actDistance);
                            // calculate the lap time and distance (NOTE: To get the per lap info!)
                            actLapDuration -= oldLapDuration;
                            oldLapDuration += actLapDuration;
                            actDistance -= oldDistance;
                            oldDistance += actDistance;

                            // Add one new Lap to the activity.
                            activity.Laps.Add(LapStartTime, actLapDuration);
                            // Update this lap with the data from the CS200.
                            ILapInfo LapInfo = activity.Laps[LapNumber];
                            LapInfo.TotalDistanceMeters = actDistance;
                            LapInfo.AverageCadencePerMinute = PolarHRM.GetIntTimeData(LapNumber, LapData.INT_AVG_CADENCE);
                            LapInfo.AverageHeartRatePerMinute = PolarHRM.GetIntTimeData(LapNumber, LapData.INT_AVE_SAMPLE) * HRFactor;

                            // Add the average values as data tracks to the activity.
                            LapEndTime = LapStartTime + actLapDuration;
                            ActTime = LapStartTime;
                            while (ActTime < LapEndTime)
                            {
                                activity.HeartRatePerMinuteTrack.Add(ActTime, LapInfo.AverageHeartRatePerMinute);
                                activity.CadencePerMinuteTrack.Add(ActTime, LapInfo.AverageCadencePerMinute);
                                ActTime += fiveSeconds;
                            }
                            activity.HeartRatePerMinuteTrack.Add(LapEndTime, LapInfo.AverageHeartRatePerMinute);
                            activity.CadencePerMinuteTrack.Add(LapEndTime, LapInfo.AverageCadencePerMinute);

                            // Add detailed Info to the notes field of ST.
                            // For test versions uncomment the following:
                            //activity.Notes += string.Format("Lap {0:d}:", LapNumber) + Environment.NewLine;
                            //activity.Notes += LapInfo.StartTime.ToShortTimeString() + ": " + LapInfo.TotalTime.ToString() + Environment.NewLine;
                            //activity.Notes += LapInfo.TotalDistanceMeters.ToString() + "m" + Environment.NewLine;
                            //activity.Notes += LapInfo.AverageCadencePerMinute.ToString() + "rpm" + Environment.NewLine;
                            //activity.Notes += LapInfo.AverageHeartRatePerMinute.ToString() + "bpm" + Environment.NewLine;

                            LapStartTime += actLapDuration;
                        }
                    }
                    // enter all data in the notes field.
                    // For test versions uncomment the following:
                    //foreach (RecData recdata in Enum.GetValues(typeof(RecData)))
                    //{
                    //    activity.Notes += recdata.ToString() + " = " + PolarHRM.GetRecParam(recdata).ToString() + Environment.NewLine;
                    //}
                }
                return true;
            }
            monitor.ErrorText = Properties.Resources.PolarImport_Import_NoFitnessFileFound;
            return false;
        }

        #endregion

        #region Private members

        /// <summary>The unique GUID of this FitnessDevice</summary>
        private Guid id;

        /// <summary>The image to represent this FitnessDevice</summary>
        private System.Drawing.Image image;

        /// <summary>The name of this FitnessDevice</summary>
        private string name;

        /// <summary>The connectiontype of this FitnessDevice. SonicLink or IR.</summary>
        private string connection;

        #endregion
    }
}
